// pages/llk/llk.js
const utils = require('../../utils/util.js')
Page({

  /**
   * 页面的初始数据
   */
  data: {
    level: 1, // 关卡
    score: 0, // 分数
    time: 0, // 倒计时用的秒数
    timer: null, // 计数器对象
    x: 5, //列数
    y: 5, //行数
    l: 4 / 100, // //游戏满盈率，最大为1(表示没有空白)，需要注意x*y*l%z=0
    z: 5, //每个相同元素出现的次数
    cur: null, // 当前点击的方块
    styleObj: {}, // 外部容器样式
    arrmap: [], // 数组
    renderArrMap: [],
    renderArr: [],
    activeIndex: -1,
    currentIndex: -1, 
    connIndex1: -1, // 连接的第一个方块下标
    connIndex2: -1, // 连接的第二个方块下标
    lineIndex: -1, // 当前连接线的下标
    lines: [ // 连接线数组
      { 
        top: 0,
        left: 0,
        width: 0,
        height: 0
      },
      { 
        top: 0,
        left: 0,
        width: 0,
        height: 0
      },
      { 
        top: 0,
        left: 0,
        width: 0,
        height: 0
      }
    ],
    isGameOver: false, // 是否结束游戏
    message: '' // 结束游戏的文案
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // 初始化游戏
    this.initGame(5, 6, 4, 80, 99, 1);
    // this.initGame(5, 6, 4, 80, 50, 2);
    // this.initGame(5, 9, 4, 80, 99, 3);
  },
  //游戏初始化，生成游戏画布》游戏数据》渲染游戏DOM
  initGame: function (x = 5, y = 5, z = 4, l = 80, time = 99, level = 1) {
    let that = this;

    // 初始化倒计时(计时器)
    this.setData({
      isGameOver: false,
      message: '',
      time,
      level,
      timer: setInterval(() => {
        this.setData({
          time: this.data.time - 1
        });

        // 如果时间为0的时候, 清除定时器, 并结束游戏
        if (this.data.time <= 0) {
          clearInterval(this.data.timer);
          this.setData({
            timer: null,
            time: 0
          });
          this.setData({
            isGameOver: true,
            message: '游戏已结束, 当前关数为第' + (this.data.level) + '关, 您的分数为:' +this.data.score,
          });
          // this.initGame(x, y, z, l);
        }
      }, 1000)
    });

    // 设置初始化外层的容器需要参数
    this.setData({
      x,
      y,
      z,
      l: l / 100,
      styleObj: {
        width: that.data.x * 60,
        height: that.data.y * 60
      }
    });

    // 处理格子数据数组的处理
    that.gameArrMap();
  },
  reStartGame() {
    this.initGame(5, 4, 4, 80, 99, 1);
  },
  shuffle2DArray(arr) {
    // 将二维数组转换为一维数组
    const flatArr = arr.flat();
    
    // 使用 Fisher-Yates 算法打乱一维数组
    for (let i = flatArr.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [flatArr[i], flatArr[j]] = [flatArr[j], flatArr[i]];
    }
    
    // 将打乱后的一维数组重新放回二维数组的相应位置
    const rows = arr.length;
    const cols = arr[0].length;
    const shuffledArr = [];
    let index = 0;
    
    for (let i = 0; i < rows; i++) {
      const row = [];
      for (let j = 0; j < cols; j++) {
        row.push(flatArr[index]);
        index++;
      }
      shuffledArr.push(row);
    }
    
    return shuffledArr;
  },
  // 每个格子数据数组的处理(包括虚拟和渲染的)
  gameArrMap: function () {
    let that = this;
    let arrmap = []; // 生成虚拟二维数组（比实际数组大一圈，方便连线计算）,并初始值均为0
    let renderArrMap = []; // 渲染方块用的数组

    let currentIndex = 0;
    for (let i = 0; i < that.data.y + 2; i++) {
      arrmap[i] = [];
      for (let j = 0; j < that.data.x + 2; j++) {
        arrmap[i][j] = {
          id: currentIndex,
          value: 0,
          show: true,
        };
        currentIndex++;
      }
      // console.log(arrmap);
    }

    let arrbase = []; // 生成基础数据一维数组
    let max = (that.data.x * that.data.y * that.data.l) / that.data.z;
    for (let m = 0; m < that.data.z; m++) {
      for (let n = 0; n < max; n++)
        arrbase[n + m * max] = n + 1;
    }

    let arrorder = []; //生成乱序数组
    let arrtemp = []; //顺序数组（临时使用）
    for (let h = 0; h < that.data.x * that.data.y; h++) {
      arrtemp[h] = h;
    }
    for (let g = 0; g < that.data.x * that.data.y; g++) {
      //从顺序数组中随机位置拿一个数，最后生成乱序数组
      let temp = Math.floor(Math.random() * arrtemp.length);
      arrorder.push(arrtemp.splice(temp, 1)[0])
    }

    //根据此顺序将基础数组添加到地图数组
    for (let o = 0; o < arrbase.length; o++) {
      arrmap[Math.floor(arrorder[o] / that.data.x) + 1][(arrorder[o] % that.data.x + 1)]['value'] = arrbase[o]
    }

    // 记录下标, 用于渲染的格子
    let current = 0;
    for (let i = 0; i < that.data.y; i++) {
      renderArrMap[i] = [];
      for (let j = 0; j < that.data.x; j++) {
        renderArrMap[i][j] = {
          id: current,
          value: arrmap[i + 1][j + 1]['value'],
          show: arrmap[i + 1][j + 1]['show'],
        };
        current++;
      }
    }
    
    // 设置值
    this.setData({
      arrmap,
      renderArrMap
    });
  },
  // 方块点击事件
  itemClick(e) {
    let that = this;

    const {
      index,
      show,
      classname
    } = e.target.dataset;

    // 如果是非展示状态或默认为list0的则不展示active状态
    if (!show || classname === 'list0') return;

    this.setData({
      activeIndex: index
    });

    //没有选中项的情况
    if (this.data.curr == null) {
      this.setData({
        currentIndex: index,
        curr: {
          index: () => index
        }
      });
    } else if (this.data.curr.index() != index) {
      //有选中项，直接进行验证
      console.log('是否连接:', that.getconnect(that.data.curr, {
        index: () => index
      }));
      //若能连接
      if (that.getconnect(that.data.curr, { index: () => index })) {
        // console.log('若能连接');
        
        this.setData({
          connIndex1: that.data.curr.index(),
          connIndex2: index,
          curr: null,
          activeIndex: -1,
        });
      } else {
        // console.log('未能连接');
        this.setData({
          curr: {
            index: () => index
          }
        });
      }
    }
  },

  // 查看是否已通关(是否含有show为true的元素)
  isElementInArray(arr, target) {
    for (let i = 0; i < arr.length; i++) {
      for (let j = 0; j < arr[i].length; j++) {
        if (arr[i][j].show === target && arr[i][j].value !== 0) {
          return true;
        }
      }
    }
    return false;
  },
  // 消除成功, 取消2个格子的显示
  hide(ai, aj, bi, bj) {
    this.data.renderArrMap[ai - 1][aj - 1].show = false;
    this.data.renderArrMap[bi - 1][bj - 1].show = false;
    this.setData({
      renderArrMap: this.data.renderArrMap
    });

    // 如果当前为第一关, 每次消除成功则得10分
    if (this.data.level == 1) {
      this.setData({
        score: this.data.score + 10
      });
    // 如果当前为第二关, 每次消除成功则得20分
    } else if (this.data.level == 2) {
      this.setData({
        score: this.data.score + 20
      });
    // 如果当前为第三关, 每次消除成功则得30分
    } else {
      this.setData({
        score: this.data.score + 30
      });
    }

    // 如果已经没有方块了, 进入下一关或者结束游戏
    if (!this.isElementInArray(this.data.renderArrMap, true)) {
      if (this.data.level === 1) {
        clearInterval(this.data.timer);
        this.setData({
          timer: null
        });
        this.initGame(5, 7, 4, 80, 99, this.data.level);
        this.setData({
          level: this.data.level + 1,
          activeIndex: -1
        });
      } else if (this.data.level === 2) {
        clearInterval(this.data.timer);
        this.setData({
          timer: null
        });
        this.initGame(5, 9, 3, 80, 50, this.data.level + 1);
        this.setData({
          level: this.data.level + 1,
          activeIndex: -1
        });
      } else {
        // 已通关
        clearInterval(this.data.timer);
        this.setData({
          level: 1,
          timer: null,
          isGameOver: true,
          message: '恭喜您, 已通关!' + ' 您的分数为:' + this.data.score,
          activeIndex: -1
        });
      }
    }
  },
  getconnect: function (a, b) {
    let that = this;
    let isopen = false;
    let ai = parseInt(a.index() / that.data.x) + 1; //因为虚拟地图比实际大一圈，所以都+1
    let aj = (a.index() % that.data.x) + 1;
    let bi = parseInt(b.index() / that.data.x) + 1;
    let bj = (b.index() % that.data.x) + 1;
    // console.log("当前对比(" + ai + "," + aj + ")和(" + bi + "," + bj + ")");
    // console.log(that.data.arrmap);
    // console.log(that.data.arrmap[ai][aj]['value'], that.data.arrmap[bi][bj]['value']);
    if (that.data.arrmap[ai][aj]['value'] != that.data.arrmap[bi][bj]['value']) {
      console.log("两次选择内容不同，不可消除");
      return false;
    } else {
      //判断是否同行或同列
      if (ai == bi) {
        //同行
        if (that.isOpen_h(that.data.arrmap, ai, aj, bj)) {
          //直线可连接
          that.data.arrmap[ai][aj].value = 0;
          that.data.arrmap[bi][bj].value = 0;
          that.setData({
            arrmap: that.data.arrmap
          });
          that.drawLine_h(ai, aj, bj, 0);
          this.hide(ai, aj, bi, bj);
          return true;
        } else {
          //三线可连接
          for (let i = 0; i < that.data.y + 2; i++) {
            if (
              that.isOpen_h(that.data.arrmap, i, aj, bj) &&
              that.isOpen_v(that.data.arrmap, aj, ai, i) &&
              that.isOpen_v(that.data.arrmap, bj, bi, i) &&
              that.data.arrmap[i][aj].value == 0 &&
              that.data.arrmap[i][bj].value == 0
            ) {
              console.log("同行三线第" + i + "行形成通路");
              that.drawLine_h(i, aj, bj, 0);
              that.drawLine_v(aj, ai, i, 1);
              that.drawLine_v(bj, bi, i, 2);
              that.data.arrmap[ai][aj].value = 0;
              that.data.arrmap[bi][bj].value = 0;
              that.setData({
                arrmap: that.data.arrmap
              });
              this.hide(ai, aj, bi, bj);
              isopen = true;
              break;
            }
          }
          return isopen;
        }
      } else if (aj == bj) {
        //同列
        if (that.isOpen_v(that.data.arrmap, aj, ai, bi)) {
          //直线可连接
          that.data.arrmap[ai][aj].value = 0;
          that.data.arrmap[bi][bj].value = 0;
          that.setData({
            arrmap: that.data.arrmap
          });
          that.drawLine_v(aj, ai, bi, 0);
          this.hide(ai, aj, bi, bj);
          return true;
        } else {
          //三线可连接
          for (let j = 0; j < that.data.x + 2; j++) {
            if (
              that.isOpen_v(that.data.arrmap, j, ai, bi) &&
              that.isOpen_h(that.data.arrmap, ai, aj, j) &&
              that.isOpen_h(that.data.arrmap, bi, bj, j) &&
              that.data.arrmap[ai][j].value == 0 &&
              that.data.arrmap[bi][j].value == 0
            ) {
              console.log("同列三线第" + j + "列形成通路");
              that.drawLine_v(j, ai, bi, 0);
              that.drawLine_h(ai, aj, j, 1);
              that.drawLine_h(bi, bj, j, 2);
              that.data.arrmap[ai][aj].value = 0;
              that.data.arrmap[bi][bj].value = 0;
              that.setData({
                arrmap: that.data.arrmap
              });
              this.hide(ai, aj, bi, bj);
              isopen = true;
              break;
            }
          }
          return isopen;
        }
      } else {
        //不同行同列
        //两条线可连
        if (
          that.data.arrmap[ai][bj].value == 0 &&
          that.isOpen_h(that.data.arrmap, ai, aj, bj) &&
          that.isOpen_v(that.data.arrmap, bj, ai, bi)
        ) {
          console.log("不同行同列与（" + ai + "," + bj + ")点两线通路");
          that.drawLine_h(ai, aj, bj, 0);
          that.drawLine_v(bj, ai, bi, 1);
          that.data.arrmap[ai][aj].value = 0;
          that.data.arrmap[bi][bj].value = 0;
          that.setData({
            arrmap: that.data.arrmap
          });
          this.hide(ai, aj, bi, bj);
          return true;
        } else if (
          that.data.arrmap[bi][aj].value == 0 &&
          that.isOpen_v(that.data.arrmap, aj, ai, bi) &&
          that.isOpen_h(that.data.arrmap, bi, aj, bj)
        ) {
          console.log("不同行同列与（" + bi + "," + aj + ")点两线通路");
          that.drawLine_v(aj, ai, bi, 0);
          that.drawLine_h(bi, aj, bj, 1);
          that.data.arrmap[ai][aj].value = 0;
          that.data.arrmap[bi][bj].value = 0;
          that.setData({
            arrmap: that.data.arrmap
          });
          this.hide(ai, aj, bi, bj);
          return true;
        } else {
          //三条线可连
          for (let i = 0; i < that.data.y + 2; i++) {
            if (
              that.isOpen_h(that.data.arrmap, i, aj, bj) &&
              that.isOpen_v(that.data.arrmap, aj, ai, i) &&
              that.isOpen_v(that.data.arrmap, bj, bi, i) &&
              that.data.arrmap[i][aj].value == 0 &&
              that.data.arrmap[i][bj].value == 0
            ) {
              console.log("不同行三线第" + i + "行形成通路");
              that.drawLine_h(i, aj, bj, 0);
              that.drawLine_v(aj, ai, i, 1);
              that.drawLine_v(bj, bi, i, 2);
              that.data.arrmap[ai][aj].value = 0;
              that.data.arrmap[bi][bj].value = 0;
              that.setData({
                arrmap: that.data.arrmap
              });
              this.hide(ai, aj, bi, bj);
              isopen = true;
              break;
            }
          }
          if (isopen) {
            this.hide(ai, aj, bi, bj);
            return isopen;
          } else {
            for (let j = 0; j < that.data.x + 2; j++) {
              if (
                that.isOpen_v(that.data.arrmap, j, ai, bi) &&
                that.isOpen_h(that.data.arrmap, ai, aj, j) &&
                that.isOpen_h(that.data.arrmap, bi, bj, j) &&
                that.data.arrmap[ai][j].value == 0 &&
                that.data.arrmap[bi][j].value == 0
              ) {
                console.log("不同列三线第" + j + "列形成通路");
                that.drawLine_v(j, ai, bi, 0);
                that.drawLine_h(ai, aj, j, 1);
                that.drawLine_h(bi, bj, j, 2);
                that.data.arrmap[ai][aj].value = 0;
                that.data.arrmap[bi][bj].value = 0;
                that.setData({
                  arrmap: that.data.arrmap
                });
                this.hide(ai, aj, bi, bj);
                isopen = true;
                break;
              }
            }
            return isopen;
          }
        }
      }
    }
  },
  //验证同行两点之间是否通畅
  isOpen_h: function (arr, i, aj, bj) {
    let a = true;
    if (Math.abs(aj - bj) != 1) {
      //不相邻，相邻直接通过，aj=bj的情况前面已经排除
      for (let k = 1; k < Math.abs(aj - bj); k++) {
        let jj = aj > bj ? bj + k : aj + k;
        // console.log(arr[i][jj].value);
        if (arr[i][jj].value != 0) {
          a = false;
          console.log("横向坐标阻塞" + i + "," + jj);
          break;
        }
      }
    }
    return a;
  },
  //验证同列两点之间是否通畅
  isOpen_v: function (arr, j, ai, bi) {
    let a = true;
    if (Math.abs(ai - bi) != 1) {
      //不相邻，相邻直接通过，ai=bi的情况前面已经排除
      for (let k = 1; k < Math.abs(ai - bi); k++) {
        let ii = ai > bi ? bi + k : ai + k;
        if (arr[ii][j].value != 0) {
          a = false;
          console.log("纵向坐标阻塞" + ii + "," + j);
          break;
        }
      }
    }
    return a;
  },

  // 画连接线
  drawLine_h: function (i, aj, bj, n) {
    let s = aj > bj ? bj : aj;
    let that = this;
    that.data.lines[n] = {
      top: 30 + 60 * [i - 1],
      left: 30 + 60 * [s - 1],
      width: Math.abs(aj - bj) * 60,
      height: 2,
    };
    that.setData({
      lineIndex: n,
      lines: that.data.lines
    });
    setTimeout(function () {
      that.data.lines[n] = {
        top: 0,
          left: 0,
          width: 0,
          height: 0
      };

      that.setData({
        lineIndex: -1,
        lines: that.data.lines
      });
    }, 60);
  },
  drawLine_v: function (j, ai, bi, n) {
    let that = this;
    let s = ai > bi ? bi : ai;
    that.data.lines[n] = {
      top: 30 + 60 * [s - 1],
      left: 30 + 60 * [j - 1],
      width: 2,
      height: Math.abs(ai - bi) * 60,
    };
    that.setData({
      lineIndex: n,
      lines: that.data.lines
    });
    setTimeout(function () {
      that.data.lines[n] = {
        top: 0,
        left: 0,
        width: 0,
        height: 0
      };
      that.setData({
        lineIndex: -1,
        lines: that.data.lines
      })
    }, 60);
  },
  isShow(id) {
    // console.log(id);
    return !(this.data.connIndex1 == id) || !(this.data.connIndex2 == id);
  }
})